package go84;

import javax.microedition.location.Criteria;
import javax.microedition.location.Location;
import javax.microedition.location.LocationException;
import javax.microedition.location.LocationListener;
import javax.microedition.location.LocationProvider;

public class MovementTracker implements LocationListener {
	class UpdateHandler implements Runnable {
		private Location updatedLocation = null;

		// Called from MovementTracker - this will handle the new location
		// update
		public synchronized void handleUpdate(Location update) throws Exception {
			done = false;
			updatedLocation = update;
			run();
			String nmea = update
					.getExtraInfo("application/X-jsr179-location-nmea");
			int satPos = nmea.indexOf('E') + 1;
			satPos = nmea.indexOf(',', satPos) + 1;
			satPos = nmea.indexOf(',', satPos) + 1;
			int satEndPos = nmea.indexOf(',', satPos);
			go84class.setSats(Integer.parseInt("0"
					+ nmea.substring(satPos, satEndPos)));
		}

		private void processUpdate(Location update) {
			l = update;
			try {
				//System.out.println(update.getQualifiedCoordinates().getLongitude());
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if(l!=null)
				go84class.updatePos(l.getQualifiedCoordinates(),
						l.getSpeed() * 3.6, (int) l.getCourse());
			/*
			 * return; try { // if we've moved more than our requisite movement
			 * distance update the website and store the new location if (l ==
			 * null) { l = update; System.out.println("0update:"+update+" l:"+
			 * l); } else if ( update.getQualifiedCoordinates().distance(
			 * l.getQualifiedCoordinates() )
			 * 
			 * > movementDistance ) { // Update the website here!!! // Note:
			 * Lat/Long are doubles!
			 * 
			 * // to get current location's latitude call the below :
			 * //update.getQualifiedCoordinates().getLatitude(); // to get
			 * current location's longitude call the below :
			 * //update.getQualifiedCoordinates().getLongitude();
			 * 
			 * l = update; System.out.println("1update:"+update+" l:"+ l);
			 * go84class
			 * .updatePos(l.getQualifiedCoordinates(),l.getSpeed()*3.6,(
			 * int)l.getCourse()); } } catch (Exception e) {
			 * System.err.println(e); }
			 */
		}

		// This method will perform the actual handling of location updates
		public void run() {
			Location locationToBeHandled = null;
			while (!done) {
				// Multi-threading
				synchronized (this) {
					// If there isn't a location to be processed try waiting and
					// see if theres any exceptions
					if (updatedLocation == null) {
						try {
							wait();
						} catch (Exception e) {
							// Handle problems
						}
					}
					// store the location to be handled and reset the
					// updatedLocation
					locationToBeHandled = updatedLocation;
					updatedLocation = null;
				}

				if (locationToBeHandled != null) {
					processUpdate(locationToBeHandled);
					done = true;
				}

			}
		}
	}

	// public Coordinates c;
	private boolean done;
	Go84 go84class;
	int hAcc, vAcc;
	// An update handler class used to handle our updates
	private UpdateHandler handler;
	private Location l;
	private LocationProvider lp;

	// What distance do we consider OK to update a new point with
	float movementDistance;

	// Constructor taking in horizontal and vertical accuracy
	public MovementTracker(int hAcc, int vAcc, Go84 go84class) {
		this.go84class = go84class;
		this.hAcc = hAcc;
		this.vAcc = vAcc;
		// Exception handling must be implemented to set a location provider
		try {
			// Upon initialization no new update to be processed
			done = false;

			// set distance at which we will recognize a location change to 50
			// meters
			movementDistance = 5.0f;

			Criteria cr = new Criteria();

			// Self-explanatory
			cr.setHorizontalAccuracy(hAcc);
			cr.setVerticalAccuracy(vAcc);

			lp = LocationProvider.getInstance(cr);

			handler = new UpdateHandler();

			// Setup a location listener that will call locationUpdated every
			// 120 seconds with a 20 second timeout
			// and a max age of 140 seconds (time to reuse old coordinates)

			lp.setLocationListener(this, 5, 3, 3);

		} catch (LocationException e) {
			// Error in init - not able to retrieve location information
		} catch (java.lang.IllegalArgumentException iae) {
			System.err.println("aaaa" + iae);
		}
	}

	// New location is waiting to be handled
	public void locationUpdated(LocationProvider provider, Location location) {
		// System.out.println("The location has changed");
		try {
			handler.handleUpdate(location);
		} catch (Exception e) {
			System.err.println(e);
		}
	}

	// If the location provider stops responding, or other strange things happen
	// to it, it will try to fix this. I think a
	// simple rerun of the constructor code will be sufficient to fix this, but
	// for now, we will keep it simple
	public void providerStateChanged(LocationProvider provider, int newState) {
		// Exception handling must be implemented to set a location provider
		try {
			// Upon initialization no new update to be processed
			done = false;

			// set distance at which we will recognize a location change to 50
			// meters
			movementDistance = 5.0f;

			Criteria cr = new Criteria();

			// Self-explanatory
			cr.setHorizontalAccuracy(hAcc);
			cr.setVerticalAccuracy(vAcc);

			lp = LocationProvider.getInstance(cr);

			handler = new UpdateHandler();

			// Setup a location listener that will call locationUpdated every
			// 120 seconds with a 20 second timeout
			// and a max age of 140 seconds (time to reuse old coordinates)

			lp.setLocationListener(this, 5, 3, 3);

		} catch (LocationException e) {
			// Error in init - not able to retrieve location information
		} catch (java.lang.IllegalArgumentException iae) {
			System.err.println("bbbb" + iae);
		}
	}

}
